/* $RCSFile: EncryptConfig.ascx.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/AddonNice/PageModules/EncryptConfig/EncryptConfig.ascx.cs $
 * $log$
 * Revision 20 2010/08/09 10:51:20  christian.surieux
 *   Added Log comment to all .aspx .ascx .master files
 * Revision 19 2010/08/09 09:43:53  christian.surieux
 *   Added Log to cs sources files
 * Revision 6 2010/08/06 19:56:25  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.Configuration;
using System.Data;
using System.Xml;
using System.IO;
using System.Security.Principal;
using System.Security.AccessControl;
using System.Collections;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.Configuration;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Globalization;

using AddonNice.Helpers;
using AddonNice.Diagnostics;
using AddonNice.Configuration;
using AddonNice.Configuration.Settings;
using AddonNice.Settings;
using AddonNice.Settings.Cache;
using AddonNice.UI;
using AddonNice.UI.DataTypes;
using AddonNice.UI.WebControls;

using Trace2   =   System.Diagnostics.Trace;

namespace AddonNice.PageModules.EncryptConfig
{

    /// <summary>
    /// Initializer class for EncryptConfig 
    /// </summary>
    public class EncryptConfigSI : PortalModuleControlSI
    {
        public EncryptConfigSI(ModuleSettingsDictionary bSettings,ISettingsOwner pm) : base()
        {
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]EncryptConfigSI Ctor BEG.",ModuleTraceSwitch.Sw.Info);
            InitSettings(bSettings,pm);
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]EncryptConfigSI Ctor END.",ModuleTraceSwitch.Sw.Info);
        }
 
        public override void InitSettings(ModuleSettingsDictionary bSettings,ISettingsOwner pm)
        {             
            if ( ModuleTraceSwitch.Sw.TraceVerbose )
                Trace2.WriteLine( "[V]EncryptConfigSI InitSettings BEG.",ModuleTraceSwitch.Sw.Info);
            
            base.InitSettings(bSettings,pm);
        }
    }

    public partial class EncryptConfig : PortalModuleControl
    {
        string SelSecName		= string.Empty;
        string user				= string.Empty;
        string strPath			= string.Empty;
        enum SectionName : int { AppSettings = 0, ConnectionStrings = 1 }
        enum AsynchAction : int { None,ProtectAppSettings , ProtectConnectionStrings, UpdateAppSettings , UpdateConnectionStrings,GiveAccess}

        AsynchAction currentAsyncAction  =   AsynchAction.None;
        /// <summary>
        /// Admin Module
        /// </summary>
        public override bool AdminModule
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// GuidID {68612464-31EB-4f8a-AFE4-6B5A68C0D903}
        /// </summary>
        public override Guid GuidID
        {
            get
            {
                return new Guid("{68612464-31EB-4f8a-AFE4-6B5A68C0D903}");
            }
        }


        // Adds an ACL entry on the specified file for the specified account.
        public static void AddFileSecurity(string fileName, string account,
            FileSystemRights rights, AccessControlType controlType)
        {
            // Get a FileSecurity object that represents the 
            // current security settings.
            FileSecurity fSecurity = File.GetAccessControl(fileName);

            // Add the FileSystemAccessRule to the security settings. 
            fSecurity.AddAccessRule(new FileSystemAccessRule(account,rights, controlType));

            // Set the new access settings.
            File.SetAccessControl(fileName, fSecurity);

        }

        /// <summary>
        /// Try to add the modify right to current user for web.config
        /// </summary>
        /// <param name="user"></param>
        void CheckAccess()
        {
            try
            {
                string wpath = Request.MapPath("web.config");
                AddFileSecurity(wpath, user, FileSystemRights.Modify, AccessControlType.Allow);
            }
            catch (Exception ex)
            {
                if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]EncryptConfig CheckAccess Module : {0}, User: {1}, ex: {2}", GetType().Name,user, ex),ModuleTraceSwitch.Sw.Info);
            }

        }

        bool ReadFileACL()
        {
            string wpath = Request.MapPath("web.config");
            FileSecurity fSecurity = File.GetAccessControl(wpath);
            bool ok = false;
            StringBuilder sb = new StringBuilder();
            foreach (FileSystemAccessRule fsa in fSecurity.GetAccessRules(true, false, typeof(NTAccount)))
            {
                if (fsa.AccessControlType == AccessControlType.Allow &&
                    (fsa.FileSystemRights & FileSystemRights.Modify) == FileSystemRights.Modify &&
                    fsa.IdentityReference.Value == user)
                    ok = true;
                sb.AppendFormat("{0}\t{1}\t{2}{3}", new object[] { fsa.IdentityReference, fsa.FileSystemRights, fsa.AccessControlType, Environment.NewLine });
            }
            TbACL.Text = sb.ToString();
            return ok;
        }

        // Install tooltips
        protected override void AddTargetToGlobalToolTipManager()
        {
            if (!IsPostBack)
            {
                ADNPage.AddToolTipTarget(AppProtectButton.ClientID, true,TootipPos.Bottom);
                ADNPage.AddToolTipTarget(CnxProtectButton.ClientID, true,TootipPos.Bottom);
                ADNPage.AddToolTipTarget(AppUpdate.ClientID, true,TootipPos.Bottom);
                ADNPage.AddToolTipTarget(CnxUpdate.ClientID, true,TootipPos.Bottom);
                ADNPage.AddToolTipTarget(BtnSetAccess.ClientID, true,TootipPos.Bottom);
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            string strp         =   Request.CurrentExecutionFilePath;
            strPath             =   strp.Substring(0, strp.LastIndexOf('/'));

            SelSecName          =   RadTabStrip1.SelectedTab.Text;
            if (ModuleTraceSwitch.Sw.TraceVerbose)
                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig Page_Load :SelSecName: {0}, strPath: {1}",SelSecName,strPath),ModuleTraceSwitch.Sw.Info);

            user                =   System.Security.Principal.WindowsIdentity.GetCurrent().Name;
            // Update buttons are activated only when textbox are modified
            AppSettingsXml.Attributes.Add("onchange","document.getElementById('"+AppUpdate.ClientID+"').disabled=false;return false;");
            CnxSettingsXml.Attributes.Add("onchange","document.getElementById('"+CnxUpdate.ClientID+"').disabled=false;return false;");

            if (string.IsNullOrEmpty(TbServerName.Text))
                TbServerName.Text = Page.Server.MachineName;
            if ( string.IsNullOrEmpty(TbUserName.Text))
                TbUserName.Text = user;
            if (!IsPostBack)
            {
                UpdateUI();
            }
        }

		/// <summary>
		/// Try to read ACL for AddonNice install folder
		/// </summary>
		void BtnSetAccess_Click(object sender, ImageClickEventArgs e)
		{
            currentAsyncAction                  =    AsynchAction.GiveAccess;
            CheckAccess();
            UpdateUI();
        }

		/// <summary>
		/// Protect/Unprotect web.config AppSettings and ConnectionStrings
		/// </summary>
		void AppProtectButton_Click(object sender, ImageClickEventArgs e)
		{
            try
            {
                // Get configuration.
                System.Configuration.Configuration config = (System.Configuration.Configuration)WebConfigurationManager.OpenWebConfiguration("~");

                ConfigurationSection appSettings    =   null;
                int tabStripId                      =   int.Parse(this.RadTabStrip1.SelectedTab.Value);
                switch (tabStripId)
                {
                    default:
                    case 0: // AppSettings
                        appSettings                 =   config.AppSettings;
                        currentAsyncAction          =    AsynchAction.ProtectAppSettings;
                        break;
                    case 1: // ConnectionStrings
                        appSettings                 =   config.ConnectionStrings;
                        currentAsyncAction          =    AsynchAction.ProtectConnectionStrings;
                        break;
                }
                if (appSettings != null)
                {
                    if (!appSettings.SectionInformation.IsProtected)
                    {
                        if (!appSettings.ElementInformation.IsLocked)
                        {
                            if (ModuleTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig AppProtectButton_Click Protecting :{0}", appSettings.SectionInformation.Name),ModuleTraceSwitch.Sw.Info);
                            // Protect the section.
                            appSettings.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
                            if (ModuleTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig AppProtectButton_Click Section {0} is now protected by {1}",
                                         appSettings.SectionInformation.Name,appSettings.SectionInformation.ProtectionProvider.Name),ModuleTraceSwitch.Sw.Info);
                        }
                        else
                            if (ModuleTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig AppProtectButton_Click Can't protect, section {0} is locked ", appSettings.SectionInformation.Name),ModuleTraceSwitch.Sw.Info);
                    }
                    else
                    {
                        if (ModuleTraceSwitch.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig AppProtectButton_Click can't protect, section {0} is already protected by {1}",
                            appSettings.SectionInformation.Name,appSettings.SectionInformation.ProtectionProvider.Name),ModuleTraceSwitch.Sw.Info);
                        if (!appSettings.ElementInformation.IsLocked)
                        {
                            appSettings.SectionInformation.UnprotectSection();
                        }
                        else
                            if (ModuleTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig AppProtectButton_Click Can't unProtect, section {0} is locked ", appSettings.SectionInformation.Name),ModuleTraceSwitch.Sw.Info);
                    }
                    // Save the encrypted/uncrypted section.
                    appSettings.SectionInformation.ForceSave = true;
                    config.Save(ConfigurationSaveMode.Full);
                    UpdateUI();
                }
            }
            catch (Exception ex)
            {
                if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]EncryptConfig AppProtectButton_Click Module : {0}, ProtectButton_OnClick ex: {1}", GetType().Name, ex),ModuleTraceSwitch.Sw.Info);
            }
        }

		void AppUpdate_Click(object sender, ImageClickEventArgs e)
		{
            try
            {
                // Get configuration.
                System.Configuration.Configuration config   =   (System.Configuration.Configuration)WebConfigurationManager.OpenWebConfiguration("~");

                ConfigurationSection appSettings            =   null;
                TextBox SettingsXml                         =   null;
                switch (int.Parse(this.RadTabStrip1.SelectedTab.Value))
                {
                    default:
                    case 0: // AppSettings
                        appSettings                         =   config.AppSettings;
                        SettingsXml                         =   AppSettingsXml;
                        AppUpdate.Enabled                   =   false;
                        currentAsyncAction                  =   AsynchAction.UpdateAppSettings;
                        break;
                    case 1: // ConnectionStrings
                        appSettings                         =   config.ConnectionStrings;
                        SettingsXml                         =   CnxSettingsXml;
                        CnxUpdate.Enabled                   =   false;
                        currentAsyncAction                  =   AsynchAction.UpdateConnectionStrings;
                        break;
                }
                if ( appSettings != null)
                {
                    if (!appSettings.SectionInformation.IsProtected)
                    {
                        if (!appSettings.ElementInformation.IsLocked)
                        {
                            try
                            {
                                if (ModuleTraceSwitch.Sw.TraceVerbose)
                                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig AppUpdate_Click update section {0} with {1}", appSettings.SectionInformation.Name, AppSettingsXml.Text),ModuleTraceSwitch.Sw.Info);
                                appSettings.SectionInformation.SetRawXml(SettingsXml.Text);
                            }
                            catch (Exception ex)
                            {
                                if (ModuleTraceSwitch.Sw.TraceError)
                                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]EncryptConfig AppUpdate_Click Module : {0}, UpdateButton_OnClick SetRawXml: {1} ex: {2}", GetType().Name,AppSettingsXml.Text,ex),ModuleTraceSwitch.Sw.Info);
                                throw;
                            }
                        }
                        else
                        {
                            if (ModuleTraceSwitch.Sw.TraceVerbose)
                                Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig AppUpdate_Click Can't update, section {0} is locked ", appSettings.SectionInformation.Name),ModuleTraceSwitch.Sw.Info);
                            return;
                        }
                    }
                    else
                    {
                        if (ModuleTraceSwitch.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig AppUpdate_Click can't update, section {0} is protected by {1}",
                            appSettings.SectionInformation.Name,appSettings.SectionInformation.ProtectionProvider.Name),ModuleTraceSwitch.Sw.Info);
                        return;
                        }

                    // Save the encrypted/decrypted section.
                    appSettings.SectionInformation.ForceSave = true;

                    config.Save();

                    UpdateUI();
                }
            }
            catch (Exception ex)
            {
                if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]EncryptConfig AppUpdate_Click Module : {0}, UpdateButton_OnClick ex: {1}", GetType().Name, ex),ModuleTraceSwitch.Sw.Info);
            }
        }

        void UpdateUI()
        {
            try
            {
                if (ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig UpdateUI Path :{0} , SelSecName: {1}", strPath, SelSecName),ModuleTraceSwitch.Sw.Info);
                // Get configuration.
                System.Configuration.Configuration config   = (System.Configuration.Configuration)WebConfigurationManager.OpenWebConfiguration("~");
                for (int i = 0; i < 3; i++)
                {
                    ConfigurationSection appSettings        =   null;
                    TextBox SettingsXml                     =   null;
                    switch (i)
                    {
                        default:
                        case 0: // AppSettings
                            appSettings                     =   config.AppSettings;
                            SettingsXml                     =   AppSettingsXml;
                            break;
                        case 1: // ConnectionStrings
                            appSettings                     =   config.ConnectionStrings;
                            SettingsXml                     =   CnxSettingsXml;
                            break;
                        case 2:
                            {
                                if (ReadFileACL())
                                    BtnSetAccess.Enabled = false;
                                return;
                            }
                    }

                    if (ModuleTraceSwitch.Sw.TraceVerbose)
                        Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig UpdateUI appSettings is null  :{0}", (appSettings == null)),ModuleTraceSwitch.Sw.Info);

                    // Set protect button appropriately.
                    if (appSettings != null)
                    {
                        // Show XML for app settings.
                        string xStr                         =   appSettings.SectionInformation.GetRawXml();
                        if (ModuleTraceSwitch.Sw.TraceVerbose)
                            Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig UpdateUI appSettings GetRawXml:{0}", xStr),ModuleTraceSwitch.Sw.Info);
                        SettingsXml.Text                    =   xStr;
                    }
                }
            }
            catch (Exception ex)
            {
                if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]EncryptConfig UpdateUI Module : {0}, ex: {1}", GetType().Name, ex),ModuleTraceSwitch.Sw.Info);
            }
        }

        bool IsProtected(SectionName SecName)
        {
            bool ret                                        =   false;
            try
            {
                string wPath                                =   PortalSettings.webConfigPath;
                if (ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig IsProtected Path: {0}, SecName: {1}", wPath, SecName),ModuleTraceSwitch.Sw.Info);
                // Get configuration.
                System.Configuration.Configuration config   =   WebConfigurationManager.OpenWebConfiguration("~");
                ConfigurationSection appSettings            =   null;
                switch (SecName)
                {
                    default:
                    case SectionName.AppSettings: 
                        appSettings                         =   config.AppSettings;
                        break;
                    case SectionName.ConnectionStrings: 
                        appSettings                         =   config.ConnectionStrings;
                        break;
                }
                ret                                 =   appSettings.SectionInformation.IsProtected;
                if (ModuleTraceSwitch.Sw.TraceVerbose)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]EncryptConfig IsProtected :{0}", ret),ModuleTraceSwitch.Sw.Info);
            }
            catch (Exception ex)
            {
                if (ModuleTraceSwitch.Sw.TraceError)
                    Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]EncryptConfig IsProtected ex: {0}", ex),ModuleTraceSwitch.Sw.Info);
                throw;
            }
            return ret;
        }

        // We add the buttons with good TExt for Protect/UnProtect
        protected override void OnPreRender(EventArgs e)
        {
			string strLoc			            =		Helpers.LocalizeHelper.GetCurrentNeutralCultureName();
			// Special code to adapt buttons to culture
            if ( ( currentAsyncAction ==    AsynchAction.ProtectAppSettings)
                || ( currentAsyncAction ==    AsynchAction.None ) )
            {
                if (IsProtected(SectionName.AppSettings))
                {
                    AppProtectButton.ImageUrl       =   portalSettings.GetImageFromThemeSkins("UnProtect_" + strLoc);
                    AppProtectButton.AlternateText  =   LocalizeHelper.Localize("CONTENTS_UNPROTECT", "Un-protect");
                    LblAppContent.Text              =   LocalizeHelper.Localize("CONTENTS_CYPHERED","Cyphered content");
                }
                else
                {
                    AppProtectButton.ImageUrl       =   portalSettings.GetImageFromThemeSkins("Protect_" + strLoc);
                    AppProtectButton.AlternateText  =   LocalizeHelper.Localize("CONTENTS_PROTECT", "Protect");
                    LblAppContent.Text              =   LocalizeHelper.Localize("CONTENTS_DECYPHERED","Un Cyphered content");
                }
                AppProtectButton.ToolTip            =   AppProtectButton.AlternateText;
            }
            if ((currentAsyncAction == AsynchAction.ProtectConnectionStrings)
                || (currentAsyncAction == AsynchAction.None))
            {
                if (IsProtected(SectionName.ConnectionStrings))
                {
                    CnxProtectButton.ImageUrl       =   portalSettings.GetImageFromThemeSkins("UnProtect_" + strLoc);
                    CnxProtectButton.AlternateText  =   LocalizeHelper.Localize("CONTENTS_UNPROTECT", "Un-protect");
                    LblCnxContent.Text              =   LocalizeHelper.Localize("CONTENTS_CYPHERED", "Cyphered content");
                }
                else
                {
                    CnxProtectButton.ImageUrl = portalSettings.GetImageFromThemeSkins("Protect_" + strLoc);
                    CnxProtectButton.AlternateText = LocalizeHelper.Localize("CONTENTS_PROTECT", "Protect");
                    LblCnxContent.Text = LocalizeHelper.Localize("CONTENTS_DECYPHERED", "Un Cyphered content");
                }
                CnxProtectButton.ToolTip            =   CnxProtectButton.AlternateText;
            }
            base.OnPreRender(e);
        }
        
        
        #region Std Overrides

        public override void  Page_PreInit(object sender, EventArgs e)
		{
			base.Page_PreInit(sender, e);
			string strLoc			            =   Helpers.LocalizeHelper.GetCurrentNeutralCultureName();
			// Special code to adapt buttons to culture
			AppUpdate.SkinID	                =	"Update_"+strLoc;
			CnxUpdate.SkinID	                =	"Update_"+strLoc;
			BtnSetAccess.SkinID			        =	"GiveAccess_"+strLoc;
		}
		
        override protected void OnInit(EventArgs e)
        {
            InitializeComponent();
            base.OnInit(e);
        }

        private void InitializeComponent()
        {
            Load					    +=  new System.EventHandler(Page_Load);
			AppProtectButton.Click      +=  new ImageClickEventHandler(AppProtectButton_Click);
			AppUpdate.Click		        +=  new ImageClickEventHandler(AppUpdate_Click);
			CnxProtectButton.Click		+=  new ImageClickEventHandler(AppProtectButton_Click);
			CnxUpdate.Click				+=  new ImageClickEventHandler(AppUpdate_Click);
			BtnSetAccess.Click		    +=  new ImageClickEventHandler(BtnSetAccess_Click);
        }


        #endregion

    }
}
